use async_trait::async_trait;
use chrono::{DateTime, TimeZone, Utc};
use reqwest::Client;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::error::Error;
use std::sync::Arc;
use std::time::Duration;
use tokio::sync::Mutex;
use tokio::time::timeout;

use crate::config::data_source_config::DataSourceConfig;
use super::{DataSource, StockQuote, SectorIndex, MarketSentiment, VolumeDistribution, MarketBreadth, VolatilityIndex};

#[derive(Clone)]
pub struct TdxDataSource {
    config: DataSourceConfig,
    client: Arc<Client>,
    cache: Arc<Mutex<HashMap<String, (DateTime<Utc>, serde_json::Value)>>>,
}

impl TdxDataSource {
    pub fn new(config: &DataSourceConfig) -> Self {
        let client = Client::builder()
            .timeout(Duration::from_secs(config.connection_timeout))
            .build()
            .expect("Failed to create HTTP client");
            
        Self {
            config: config.clone(),
            client: Arc::new(client),
            cache: Arc::new(Mutex::new(HashMap::new())),
        }
    }
    
    async fn fetch_with_cache<T>(&self, url: &str, cache_key: &str, ttl_seconds: u64) -> Result<T, Box<dyn Error + Send + Sync>> 
    where 
        T: for<'de> Deserialize<'de> + Send + Sync + 'static 
    {
        let now = Utc::now();
        
        // 检查缓存
        let mut cache = self.cache.lock().await;
        if let Some((timestamp, cached_data)) = cache.get(cache_key) {
            let age = now.signed_duration_since(*timestamp).num_seconds() as u64;
            if age < ttl_seconds {
                // 缓存有效，反序列化并返回
                return Ok(serde_json::from_value(cached_data.clone())?);
            }
        }
        
        // 缓存无效或不存在，发起请求
        let response = match timeout(
            Duration::from_secs(self.config.connection_timeout),
            self.client.get(url).send()
        ).await {
            Ok(result) => result?,
            Err(_) => return Err("Request timeout".into()),
        };
        
        if !response.status().is_success() {
            return Err(format!("API error: {}", response.status()).into());
        }
        
        let data: serde_json::Value = response.json().await?;
        
        // 更新缓存
        cache.insert(cache_key.to_string(), (now, data.clone()));
        
        // 反序列化并返回
        Ok(serde_json::from_value(data)?)
    }
    
    fn build_url(&self, path: &str) -> String {
        format!("{}{}", self.config.api_endpoint, path)
    }
}

#[async_trait]
impl DataSource for TdxDataSource {
    async fn get_stock_quote(&self, symbol: &str) -> Result<StockQuote, Box<dyn Error + Send + Sync>> {
        // 构建API URL
        let url = self.build_url(&format!("/quotes?symbol={}", symbol));
        
        // 定义TDX API返回的数据结构
        #[derive(Debug, Deserialize)]
        struct TdxQuote {
            code: String,
            name: String,
            price: f64,
            volume: f64,
            amount: f64,
            bid1: f64,
            bid1_vol: f64,
            ask1: f64,
            ask1_vol: f64,
            time: String, // 格式: "YYYYMMDD HH:MM:SS"
        }
        
        // 获取数据
        let tdx_quote: TdxQuote = self.fetch_with_cache(&url, &format!("quote_{}", symbol), 60).await?;
        
        // 解析时间戳
        let timestamp = chrono::NaiveDateTime::parse_from_str(&tdx_quote.time, "%Y%m%d %H:%M:%S")?;
        let timestamp = Utc.from_utc_datetime(&timestamp);
        
        // 转换为通用格式
        Ok(StockQuote {
            symbol: symbol.to_string(),
            timestamp,
            price: tdx_quote.price,
            volume: tdx_quote.volume,
            amount: tdx_quote.amount,
            bid_price: tdx_quote.bid1,
            ask_price: tdx_quote.ask1,
            bid_volume: tdx_quote.bid1_vol,
            ask_volume: tdx_quote.ask1_vol,
        })
    }
    
    async fn get_sector_indices(&self) -> Result<Vec<SectorIndex>, Box<dyn Error + Send + Sync>> {
        // 构建API URL
        let url = self.build_url("/indices/sector");
        
        // 定义TDX API返回的数据结构
        #[derive(Debug, Deserialize)]
        struct TdxSectorIndex {
            code: String,
            name: String,
            price: f64,
            change: f64,
            pct_chg: f64,
            time: String, // 格式: "YYYYMMDD HH:MM:SS"
        }
        
        // 获取数据
        let tdx_indices: Vec<TdxSectorIndex> = self.fetch_with_cache(&url, "sector_indices", 300).await?;
        
        // 转换为通用格式
        let mut indices = Vec::new();
        for idx in tdx_indices {
            // 解析时间戳
            let timestamp = chrono::NaiveDateTime::parse_from_str(&idx.time, "%Y%m%d %H:%M:%S")?;
            let timestamp = Utc.from_utc_datetime(&timestamp);
            
            indices.push(SectorIndex {
                code: idx.code,
                name: idx.name,
                value: idx.price,
                change: idx.change,
                change_percent: idx.pct_chg,
                timestamp,
            });
        }
        
        Ok(indices)
    }
    
    async fn get_market_sentiment(&self) -> Result<MarketSentiment, Box<dyn Error + Send + Sync>> {
        // 构建API URL
        let url = self.build_url("/market/sentiment");
        
        // 定义TDX API返回的数据结构
        #[derive(Debug, Deserialize)]
        struct TdxMarketSentiment {
            fear_greed: f64,
            put_call: f64,
            vix: Option<f64>,
            bullish: Option<f64>,
            bearish: Option<f64>,
            time: String, // 格式: "YYYYMMDD HH:MM:SS"
        }
        
        // 获取数据
        let sentiment: TdxMarketSentiment = self.fetch_with_cache(&url, "market_sentiment", 600).await?;
        
        // 解析时间戳
        let timestamp = chrono::NaiveDateTime::parse_from_str(&sentiment.time, "%Y%m%d %H:%M:%S")?;
        let timestamp = Utc.from_utc_datetime(&timestamp);
        
        // 转换为通用格式
        Ok(MarketSentiment {
            timestamp,
            fear_greed_index: sentiment.fear_greed,
            put_call_ratio: sentiment.put_call,
            vix: sentiment.vix,
            bullish_percent: sentiment.bullish,
            bearish_percent: sentiment.bearish,
        })
    }
    
    async fn get_volume_distribution(&self) -> Result<VolumeDistribution, Box<dyn Error + Send + Sync>> {
        // 构建API URL
        let url = self.build_url("/market/volume");
        
        // 定义TDX API返回的数据结构
        #[derive(Debug, Deserialize)]
        struct TdxVolumeDistribution {
            total: f64,
            up: f64,
            down: f64,
            distribution: HashMap<String, f64>,
            time: String, // 格式: "YYYYMMDD HH:MM:SS"
        }
        
        // 获取数据
        let volume: TdxVolumeDistribution = self.fetch_with_cache(&url, "volume_distribution", 300).await?;
        
        // 解析时间戳
        let timestamp = chrono::NaiveDateTime::parse_from_str(&volume.time, "%Y%m%d %H:%M:%S")?;
        let timestamp = Utc.from_utc_datetime(&timestamp);
        
        // 转换为通用格式
        Ok(VolumeDistribution {
            timestamp,
            total_volume: volume.total,
            up_volume: volume.up,
            down_volume: volume.down,
            distribution: volume.distribution,
        })
    }
    
    async fn get_market_breadth(&self) -> Result<MarketBreadth, Box<dyn Error + Send + Sync>> {
        // 构建API URL
        let url = self.build_url("/market/breadth");
        
        // 定义TDX API返回的数据结构
        #[derive(Debug, Deserialize)]
        struct TdxMarketBreadth {
            advancing: i32,
            declining: i32,
            unchanged: i32,
            new_highs: i32,
            new_lows: i32,
            time: String, // 格式: "YYYYMMDD HH:MM:SS"
        }
        
        // 获取数据
        let breadth: TdxMarketBreadth = self.fetch_with_cache(&url, "market_breadth", 300).await?;
        
        // 解析时间戳
        let timestamp = chrono::NaiveDateTime::parse_from_str(&breadth.time, "%Y%m%d %H:%M:%S")?;
        let timestamp = Utc.from_utc_datetime(&timestamp);
        
        // 计算涨跌比率
        let advance_decline_ratio = if breadth.declining > 0 {
            breadth.advancing as f64 / breadth.declining as f64
        } else {
            f64::INFINITY
        };
        
        // 转换为通用格式
        Ok(MarketBreadth {
            timestamp,
            advancing_issues: breadth.advancing,
            declining_issues: breadth.declining,
            unchanged_issues: breadth.unchanged,
            new_highs: breadth.new_highs,
            new_lows: breadth.new_lows,
            advance_decline_ratio,
        })
    }
    
    async fn get_volatility_indices(&self) -> Result<Vec<VolatilityIndex>, Box<dyn Error + Send + Sync>> {
        // 构建API URL
        let url = self.build_url("/market/volatility");
        
        // 定义TDX API返回的数据结构
        #[derive(Debug, Deserialize)]
        struct TdxVolatilityIndex {
            name: String,
            historical: f64,
            implied: f64,
            time: String, // 格式: "YYYYMMDD HH:MM:SS"
        }
        
        // 获取数据
        let volatility_indices: Vec<TdxVolatilityIndex> = self.fetch_with_cache(&url, "volatility_indices", 600).await?;
        
        // 转换为通用格式
        let mut indices = Vec::new();
        for idx in volatility_indices {
            // 解析时间戳
            let timestamp = chrono::NaiveDateTime::parse_from_str(&idx.time, "%Y%m%d %H:%M:%S")?;
            let timestamp = Utc.from_utc_datetime(&timestamp);
            
            indices.push(VolatilityIndex {
                timestamp,
                historical_volatility: idx.historical,
                implied_volatility: idx.implied,
                name: idx.name,
            });
        }
        
        Ok(indices)
    }
    
    fn name(&self) -> &str {
        "TDX"
    }
}